home *** CD-ROM | disk | FTP | other *** search
/ Precision Software Appli…tions Silver Collection 1 / Precision Software Applications Silver Collection Volume One (PSM) (1993).iso / windows / games / xlmath21.arj / SOURCE.ZIP / XLMDLG.C < prev    next >
C/C++ Source or Header  |  1993-04-10  |  18KB  |  679 lines

  1.  
  2. /*----------------------------------------------------------------------*\
  3.  XLMDLG.C - Dialog Box functions
  4.  =========
  5.  
  6.  Copyright    1992 by Roy Kari
  7.  
  8.  Author:    Roy Kari
  9.              Dept. of Chemistry
  10.             Laurentian University
  11.             Sudbury, Ont.
  12.             Canada        P3E 2C6
  13.             (705) 675-1151
  14.             Internet: "ROY@NICKEL.LAURENTIAN.CA"
  15.  
  16.     All dialog box procedures involve 4 distinct steps:
  17.  
  18.     1.    Prepare a textual range from the current selection and
  19.         use that range to prompt the user,
  20.  
  21.     2.    Get the user defined range and coerce the range to values,
  22.  
  23.     3.    Convert the values from XLOPER's to a floating point array and
  24.         call the custom function (see 2nd thoughts in XLMATH.C),
  25.  
  26.     4.    Receive the returned values from the custom function and put 
  27.         these values into the Excel worksheet.
  28.  
  29.     For an illustration, see the function CommDlg1()
  30.     
  31. \*----------------------------------------------------------------------*/
  32.  
  33. /* --------------------------< Include files >--------------------- */
  34.  
  35. #define WIN31
  36. #define _MSC_VER 700
  37.  
  38. #include <windows.h>
  39. #include <xlcall.h>
  40.  
  41. #include <framewrk.h>
  42. #include "xlmath.h"
  43. #include "xlutil.h"
  44.  
  45. /* -------< Forward dialog helper functions >--------------------- */
  46.  
  47. int PASCAL CommDlg1(LPXLOPER( FAR PASCAL __export *lpFn)(LPFP), 
  48.             LPSTR *prgDlg, WORD rgDlgRows, WORD InRow, WORD OutRow);
  49. int PASCAL CommDlg2(LPXLOPER( FAR PASCAL __export *lpFn)(LPFP,LPFP), 
  50.                     LPSTR *prgDlg, WORD rgDlgRows, WORD InRow1, 
  51.                     WORD InRow2, WORD OutRow);
  52. LPFP PASCAL CopyXloperToFp(LPXLOPER pxArray);
  53. LPFP PASCAL GetxlFpValues(LPXLOPER pxDialog, WORD wDlgRow);
  54. int PASCAL SetValues(LPXLOPER pxValues);
  55.  
  56.  
  57. //
  58. // CopyXloperToxlFp() - copy values in xloper to fp structure
  59. //
  60. LPFP PASCAL CopyXloperToFp(LPXLOPER pxArray)
  61. {
  62.     LPFP pfArray;
  63.     LPXLOPER pxSrc = pxArray->val.array.lparray;
  64.     WORD wRows = pxArray->val.array.rows;
  65.     WORD wCols = pxArray->val.array.columns;
  66.     WORD i, j, ij;
  67.  
  68.     if (pxArray->xltype != xltypeMulti)
  69.     {
  70.         ErrorHandler(XLU_NO_ARRAY);
  71.         return NULL;
  72.     }
  73.     pfArray = GetMem( (sizeof(double)*wRows*wCols) +2*sizeof(WORD));
  74.     if (pfArray != NULL)
  75.     {
  76.         pfArray->wRows = wRows;
  77.         pfArray->wCols = wCols;
  78.  
  79.         ij=0;
  80.         for (i=0; i<wRows; i++)
  81.         {
  82.             for (j=0; j<wCols; j++)
  83.             {
  84.                 pfArray->Data[ij+j] = pxSrc->val.num;
  85.                 pxSrc++;
  86.             }
  87.             ij += wCols;
  88.         }
  89.     }
  90.     return pfArray;
  91. }
  92.  
  93. //
  94. //     SetValues() - xlSets values in range specified by dialog box
  95. //
  96. int PASCAL SetValues(LPXLOPER pxValues)
  97. {
  98.     XLOPER xResult;
  99.  
  100.  
  101.     // strip xlbitDLLFree, will free internally
  102.     if ((pxValues->xltype & xlbitDLLFree) != 0)
  103.     {
  104.         pxValues->xltype = pxValues->xltype ^ xlbitDLLFree;
  105.     }
  106.  
  107.     // gxOutRef previously created. Now make it a rectangular
  108.     // range from top-right & xlMulti rows and columns
  109.     // if error return, then use range previously defined
  110.     if (pxValues->xltype != xltypeErr)
  111.     {
  112.         RefSetRectangle(&gxOutRef, pxValues->val.array.rows,
  113.             (BYTE)pxValues->val.array.columns);
  114.     }
  115.     
  116.     // if not overlapped set values
  117.     if (!IsReferencesOverlapped((LPXLOPER)&gxInRef, (LPXLOPER)&gxOutRef))
  118.     {
  119.         Excel(xlSet, &xResult, 2, (LPXLOPER)&gxOutRef, (LPXLOPER)pxValues);
  120.     }
  121.  
  122.     
  123.     // If NOT error return, then free the memory allocated
  124.     // to returned xloper array
  125.     if (pxValues->xltype != xltypeErr)
  126.     {
  127.         // free the memory & set NULL
  128.         xlAutoFree((LPVOID)pxValues);
  129.     }    
  130.  
  131.     return 1;
  132. }
  133.  
  134. /*----------------------------------------------------------------------*\
  135.  
  136.                         Dialog Interface Functions
  137.  
  138.     The convention is that a dialog box will invoke function
  139.     fXyz() which in turn will invoke Xyz() which finally invokes
  140.     _Xyz(). For example fSmoothWeight() which invokes SmoothWeight()
  141.     which invokes _SmoothWeight(). The following is an illustration.
  142.  
  143.     fSmoothWeight() handles the dialog box,getting the user input and
  144.     the data. This function must be written by you and registered with
  145.     Excel as a custom command.
  146.  
  147.     SmoothWeight() is the custom function which interfaces with the
  148.     library routine _SmoothWeight(). This function must also
  149.     be written by you and can usually be registered with Excel
  150.     as a custom function.
  151.  
  152.     _SmoothWeight() is a C library function which actually does the work.
  153.     This function you can usually pick up from somewhere else such as
  154.     I did from Quinn-Curtis.
  155.  
  156.     Easy, isn't it!
  157.     
  158. \*----------------------------------------------------------------------*/
  159.  
  160. int FAR PASCAL __export fDiagonalize(void)
  161. {
  162.     return (CommDlg1(Diagonalize, &rgDlgDiag[0][0], (WORD)rgDlgDiagRows,
  163.     (WORD)DIAG_IN_ROW, (WORD)DIAG_OUT_ROW));
  164. }
  165.  
  166. int FAR PASCAL __export fMODensity(void)
  167. {
  168.     return (CommDlg2(MODensity, &rgDlgMO[0][0], (WORD)rgDlgMORows,
  169.     (WORD)MO_COEF_ROW, (WORD)MO_OCC_ROW, (WORD)MO_OUT_ROW));
  170. }
  171.  
  172. int FAR PASCAL __export fCubicSplines(void)
  173. {
  174.     return (CommDlg2(CubicSplines, &rgDlgSpline[0][0], rgSplineDlgRows,
  175.     SPLINE_XVAR_ROW, SPLINE_YVAR_ROW, SPLINE_OUT_ROW));
  176. }
  177.  
  178. int FAR PASCAL __export fSmoothWt(void)
  179. {
  180.     return(CommDlg2(SmoothWeights, &rgDlgWtSmooth[0][0], rgWtSmoothDlgRows,
  181.     WTSMOOTH_DATA_ROW, WTSMOOTH_WEIGHT_ROW, WTSMOOTH_OUT_ROW));
  182. }
  183. int FAR PASCAL __export fCustomFit(void)
  184. {
  185.     return(CommDlg2(CustomFit, &rgDlgCustomFit[0][0], rgCustomFitDlgRows,
  186.     CFIT_DATA_ROW, CFIT_PARM_ROW, CFIT_OUT_ROW));
  187. }
  188.  
  189. /*----------------------------------------------------------------------*\
  190.                     Common Dialog Functions
  191.  
  192.     In many cases, a dialog box will require one input and one
  193.     output range. This general case is implimented in the routine
  194.     CommDlg1() below. Other cases require two input ranges and one
  195.     output range. These are implimented in CommDlg2() below. In still
  196.     others, one requires a unique dialog box and those must be
  197.     implimented as unique dialog box functions, Ugh!
  198.     
  199. \*----------------------------------------------------------------------*/
  200.  
  201. //
  202. //    CommDlg1() - general function to display a dialog box with
  203. //                 two range arguments; input & output range
  204. //
  205. int PASCAL CommDlg1(LPXLOPER(FAR PASCAL __export *lpFn)(LPFP), 
  206.                             LPSTR *prgDlg, WORD rgDlgRows, 
  207.                             WORD InRow, WORD OutRow)
  208. {
  209.     int xlRet;
  210.     XLOPER xDialog;
  211.     XLOPER xDialogReturned;
  212.  
  213.     XLOPER xIn, xOut, xValues;
  214.     LPXLOPER pxValueOut = NULL;
  215.     LPFP lpfpInput = NULL;
  216.  
  217.     //    STEP 1: prepare the dialog box
  218.     
  219.     // get the SheetiD for the active sheet
  220.     if (!GetActiveSheetId())
  221.     {
  222.         // no active sheet; error emit in GetActiveSheet()
  223.         return 0;
  224.     }
  225.  
  226.     // init the dialog xlMulti from definitions in header file
  227.     if (InitDialog( (LPXLOPER)&xDialog, prgDlg, rgDlgRows) == NULL)
  228.     {
  229.         return 0;
  230.     }
  231.  
  232.     // get selection in text form
  233.     GetRefTextFromSelection((LPXLOPER)&xIn, (LPXLOPER)&xOut, 1);
  234.     
  235.     // stuff into dialog box
  236.     SetInitialRange((LPXLOPER)&xIn, (LPXLOPER)&xDialog, InRow);
  237.     SetInitialRange((LPXLOPER)&xOut, (LPXLOPER)&xDialog, OutRow);
  238.  
  239.     // show dialog box
  240.     xlRet =Excel(xlfDialogBox, (LPXLOPER)&xDialogReturned, 1, (LPXLOPER)&xDialog);
  241.  
  242.     //    STEP 2: coerce the values and copy them into a FP array
  243.     
  244.     // free Excel str & xDialog
  245.     Excel(xlFree,0,1,(LPXLOPER)&xIn);
  246.     Excel(xlFree,0,1,(LPXLOPER)&xOut);
  247.     FreeMem((LPVOID)xDialog.val.array.lparray);
  248.     if (xlRet != xlretSuccess || xDialogReturned.xltype != xltypeMulti)
  249.         return 0;
  250.  
  251.     // make global input ref based on dialog range
  252.     if (CreateGlobalRef((LPXLOPER)&gxInRef, (LPXLOPER)&xDialogReturned, 
  253.             InRow))
  254.     {
  255.         // coerce to multi
  256.         Excel(xlCoerce, &xValues, 1, (LPXLOPER)&gxInRef);
  257.  
  258.         // convert to floating point array
  259.         lpfpInput = CopyXloperToFp(&xValues);
  260.         Excel(xlFree, 0, 1, (LPXLOPER)&xValues);
  261.         if (lpfpInput)
  262.         {
  263.  
  264.             //    STEP 3: Call the custom function
  265.             
  266.             //    call the function which returns LPXLOPER
  267.             pxValueOut = (*lpFn)(lpfpInput);
  268.             FreeMem(lpfpInput);
  269.  
  270.             //    STEP 4: Set the returned values into the Excel sheet
  271.             
  272.             //  set the values
  273.             if (pxValueOut)
  274.             {
  275.                 // create global output ref based on dialog
  276.                 if (CreateGlobalRef((LPXLOPER)&gxOutRef, 
  277.                         (LPXLOPER)&xDialogReturned,OutRow))
  278.                 {
  279.                     // set the values to sheet & free memory
  280.                     SetValues(pxValueOut);
  281.                 }
  282.             }
  283.         }
  284.     }
  285.     Excel(xlFree, 0, 1, (LPXLOPER)&xDialogReturned);
  286.     return 1;
  287. }
  288. //
  289. //    CommDlg2() - general function to display a dialog box with
  290. //                 three range arguments; input1, input2 & output range
  291. //
  292.  
  293. int PASCAL CommDlg2(LPXLOPER( FAR PASCAL __export *lpFn)(LPFP,LPFP), 
  294.                     LPSTR *prgDlg, WORD rgDlgRows, WORD InRow1, 
  295.                     WORD InRow2, WORD OutRow)
  296. {
  297.     int xlRet;
  298.     XLOPER xDialog;
  299.     XLOPER xDialogReturned;
  300.  
  301.     XLOPER xIn1, xIn2, xOut, xTemp;
  302.     LPXLOPER pxValueOut = NULL;
  303.     LPFP lpfpArg1, lpfpArg2;
  304.  
  305.     if (!GetActiveSheetId())
  306.     {
  307.         // no active sheet; error emit in GetActiveSheet()
  308.         return 0;
  309.     }
  310.  
  311.     // init the dialog xlMulti
  312.     if (InitDialog( (LPXLOPER)&xDialog, prgDlg, rgDlgRows)==NULL)
  313.     {
  314.         return 0;
  315.     }
  316.  
  317.     // get selection in text form for In1 & In2
  318.     GetRefTextFromSelection((LPXLOPER)&xIn1, (LPXLOPER)&xIn2, 1);
  319.     GetRefTextFromSelection((LPXLOPER)&xTemp, (LPXLOPER)&xOut, 2);
  320.     
  321.     // stuff into dialog box
  322.     SetInitialRange((LPXLOPER)&xIn1,  (LPXLOPER)&xDialog, InRow1);
  323.     SetInitialRange((LPXLOPER)&xIn2, (LPXLOPER)&xDialog, InRow2);
  324.     SetInitialRange((LPXLOPER)&xOut, (LPXLOPER)&xDialog, OutRow);
  325.  
  326.     // show dialog box
  327.     xlRet =Excel(xlfDialogBox, (LPXLOPER)&xDialogReturned, 1, (LPXLOPER)&xDialog);
  328.  
  329.     // free Excel str & xDialog
  330.     Excel(xlFree,0,1,(LPXLOPER)&xTemp);
  331.     Excel(xlFree,0,1,(LPXLOPER)&xIn1);
  332.     Excel(xlFree,0,1,(LPXLOPER)&xIn2);
  333.     Excel(xlFree,0,1,(LPXLOPER)&xOut);
  334.     FreeMem((LPVOID)xDialog.val.array.lparray);
  335.     if (xlRet != xlretSuccess || xDialogReturned.xltype != xltypeMulti)
  336.         return 0;
  337.  
  338.     // get Arg1 & Arg2
  339.     if (CreateGlobalRef(&gxInRef, &xDialogReturned, InRow1))
  340.     {
  341.         Excel(xlCoerce, (LPXLOPER)&xTemp, 1, (LPXLOPER)&gxInRef);
  342.         lpfpArg1 = CopyXloperToFp(&xTemp);
  343.         Excel(xlFree, 0, 1, (LPXLOPER)&xTemp);
  344.     }
  345.     if (lpfpArg1 ==NULL)
  346.     {
  347.         goto abort;
  348.     }
  349.     if (CreateGlobalRef(&gxInRef, &xDialogReturned, InRow2))
  350.     {
  351.         Excel(xlCoerce, (LPXLOPER)&xTemp, 1, (LPXLOPER)&gxInRef);
  352.         lpfpArg2 = CopyXloperToFp(&xTemp);
  353.         Excel(xlFree, 0, 1, (LPXLOPER)&xTemp);
  354.     }
  355.     if (lpfpArg2 == NULL)
  356.     {
  357.         FreeMem(lpfpArg1);
  358.         goto abort;
  359.     }
  360.     
  361.     // call the function
  362.     pxValueOut = (*lpFn)(lpfpArg1, lpfpArg2);
  363.     FreeMem(lpfpArg1);
  364.     FreeMem(lpfpArg2);
  365.  
  366.     // set the values
  367.     if (pxValueOut)
  368.     {
  369.         if (CreateGlobalRef(&gxOutRef, &xDialogReturned, OutRow))
  370.         {
  371.             SetValues(pxValueOut);
  372.         }
  373.     }
  374.  
  375. abort:
  376.     Excel(xlFree, 0, 1, (LPXLOPER)&xDialogReturned);
  377.  
  378.     return 1;
  379.  
  380. }
  381. /*----------------------------------------------------------------------*\
  382.  
  383.                         Unique Dialog Boxes
  384.                         
  385. \*----------------------------------------------------------------------*/
  386. // fPolyCurveFit() - display dialog box for Polynolial curve fitting
  387. //
  388. int FAR PASCAL __export fPolyCurveFit(void)
  389. {
  390.     int xlRet;
  391.     XLOPER xDialog;
  392.     XLOPER xDialogReturned;
  393.  
  394.     XLOPER xXvar, xYvar, xOrder, xOut, xTemp;
  395.     LPXLOPER pxValueOut = NULL;
  396.     LPFP lpfpXvar = NULL;
  397.     LPFP lpfpYvar = NULL;
  398.  
  399.     if (!GetActiveSheetId())
  400.     {
  401.         // no active sheet; error emit in GetActiveSheet()
  402.         return 0;
  403.     }
  404.  
  405.     // init the dialog xlMulti
  406.     if (InitDialog( (LPXLOPER)&xDialog, &rgDlgPoly[0][0], rgPolyDlgRows)==NULL)
  407.     {
  408.         return 0;
  409.     }
  410.  
  411.     // get selection in text form for Xvar & Yvar
  412.     GetRefTextFromSelection((LPXLOPER)&xXvar, (LPXLOPER)&xYvar, 1);
  413.     GetRefTextFromSelection((LPXLOPER)&xTemp, (LPXLOPER)&xOut, 2);
  414.     
  415.     // stuff into dialog box
  416.     SetInitialRange((LPXLOPER)&xXvar,  (LPXLOPER)&xDialog, POLY_XVAR_ROW);
  417.     SetInitialRange((LPXLOPER)&xYvar, (LPXLOPER)&xDialog, POLY_YVAR_ROW);
  418.     SetInitialRange((LPXLOPER)&xOut, (LPXLOPER)&xDialog, POLY_OUT_ROW);
  419.  
  420.     // show dialog box
  421.     xlRet =Excel(xlfDialogBox, (LPXLOPER)&xDialogReturned, 1, (LPXLOPER)&xDialog);
  422.  
  423.     // free Excel str & xDialog
  424.     Excel(xlFree,0,1,(LPXLOPER)&xTemp);
  425.     Excel(xlFree,0,1,(LPXLOPER)&xXvar);
  426.     Excel(xlFree,0,1,(LPXLOPER)&xYvar);
  427.     Excel(xlFree,0,1,(LPXLOPER)&xOut);
  428.     FreeMem((LPVOID)xDialog.val.array.lparray);
  429.     if (xlRet != xlretSuccess || xDialogReturned.xltype != xltypeMulti)
  430.         return 0;
  431.  
  432.     // get Xvar & Yvar
  433.     if (CreateGlobalRef(&gxInRef, &xDialogReturned, POLY_XVAR_ROW))
  434.     {
  435.         Excel(xlCoerce, (LPXLOPER)&xTemp, 1, (LPXLOPER)&gxInRef);
  436.         lpfpXvar = CopyXloperToFp(&xTemp);
  437.         Excel(xlFree, 0, 1, (LPXLOPER)&xTemp);
  438.     }
  439.     if (lpfpXvar ==NULL)
  440.         goto abort;
  441.  
  442.     if (CreateGlobalRef(&gxInRef, &xDialogReturned, POLY_YVAR_ROW))
  443.     {
  444.         Excel(xlCoerce, (LPXLOPER)&xTemp, 1, (LPXLOPER)&gxInRef);
  445.         lpfpYvar = CopyXloperToFp(&xTemp);
  446.         Excel(xlFree, 0, 1, (LPXLOPER)&xTemp);
  447.     }
  448.     if (lpfpYvar == NULL)
  449.     {
  450.         FreeMem(lpfpXvar);
  451.         goto abort;
  452.     }
  453.  
  454.     // Get order
  455.     Excel(xlCoerce, (LPXLOPER)&xOrder, 2,
  456.             (LPXLOPER)&xDialogReturned.val.array.lparray[POLY_ORDER_ROW*7+6],
  457.             TempInt(xltypeInt));
  458.     if (xOrder.xltype == xltypeInt)
  459.     {
  460.         // call the function
  461.         CreateGlobalRef(&gxOutRef, &xDialogReturned, POLY_OUT_ROW);
  462.         pxValueOut = PolyCurveFit(lpfpXvar, lpfpYvar, xOrder.val.w);
  463.     }
  464.     else
  465.     {
  466.         ErrorHandler(XLD_BAD_DIALOG);
  467.     }
  468.  
  469.     FreeMem(lpfpXvar);
  470.     FreeMem(lpfpYvar);
  471.  
  472.     // set the values
  473.     if (pxValueOut)
  474.     {
  475.         if (CreateGlobalRef(&gxOutRef, &xDialogReturned, POLY_OUT_ROW))
  476.         {
  477.             SetValues(pxValueOut);
  478.         }
  479.     }
  480. abort:
  481.     Excel(xlFree, 0, 1, (LPXLOPER)&xDialogReturned);
  482.  
  483.     return 1;
  484. }
  485.  
  486. //
  487. // fSmoothSg() - display dialog box for SG smoothing
  488. //
  489. int FAR PASCAL __export fSmoothSg(void)
  490. {
  491.     int xlRet;
  492.     XLOPER xDialog;
  493.     XLOPER xDialogReturned;
  494.  
  495.     XLOPER xData,xSmoothNum, xDerivNum, xOut;
  496.     LPXLOPER pxValueOut = NULL;
  497.     LPFP lpfpData = NULL;
  498.  
  499.     if (!GetActiveSheetId())
  500.     {
  501.         // no active sheet; error emit in GetActiveSheet()
  502.         return 0;
  503.     }
  504.  
  505.     // init the dialog xlMulti
  506.     if (InitDialog( (LPXLOPER)&xDialog, &rgDlgSgSmooth[0][0], rgSgSmoothDlgRows)==NULL)
  507.     {
  508.         return 0;
  509.     }
  510.     // get selection in text form
  511.     GetRefTextFromSelection((LPXLOPER)&xData, (LPXLOPER)&xOut, 1);
  512.     
  513.     // stuff into dialog box
  514.     SetInitialRange((LPXLOPER)&xData, (LPXLOPER)&xDialog, SGSMOOTH_DATA_ROW);
  515.     SetInitialRange((LPXLOPER)&xOut, (LPXLOPER)&xDialog, SGSMOOTH_OUT_ROW);
  516.  
  517.     
  518.     // show dialog box
  519.     xlRet =Excel(xlfDialogBox, (LPXLOPER)&xDialogReturned, 1, (LPXLOPER)&xDialog);
  520.  
  521.     // free Excel str & xDialog
  522.     Excel(xlFree,0,1,(LPXLOPER)&xData);
  523.     Excel(xlFree,0,1,(LPXLOPER)&xOut);
  524.     FreeMem((LPVOID)xDialog.val.array.lparray);
  525.     if (xlRet != xlretSuccess || xDialogReturned.xltype != xltypeMulti)
  526.         return 0;
  527.  
  528.  
  529.     // get Data values
  530.     if (CreateGlobalRef(&gxInRef, &xDialogReturned, SGSMOOTH_DATA_ROW))
  531.     {
  532.         Excel(xlCoerce, (LPXLOPER)&xData, 1, (LPXLOPER)&gxInRef);
  533.         lpfpData = CopyXloperToFp(&xData);
  534.         Excel(xlFree, 0, 1, (LPXLOPER)&xData);
  535.     }
  536.     if (lpfpData)
  537.     {
  538.         // get SmoothNum & DerivNum
  539.         Excel(xlCoerce, (LPXLOPER)&xSmoothNum, 2,
  540.         (LPXLOPER)&xDialogReturned.val.array.lparray[SGSMOOTH_SMOOTHNUM_ROW*7+6],
  541.             TempInt(xltypeInt));
  542.         Excel(xlCoerce, (LPXLOPER)&xDerivNum, 2,
  543.         (LPXLOPER)&xDialogReturned.val.array.lparray[SGSMOOTH_DERIVNUM_ROW*7+6],
  544.             TempInt(xltypeInt));
  545.  
  546.         //    call the function
  547.         if ( (xSmoothNum.xltype == xltypeInt) && 
  548.              (xDerivNum.xltype == xltypeInt))
  549.         {
  550.             pxValueOut = SmoothSG(lpfpData, xSmoothNum.val.w, xDerivNum.val.w);
  551.         }
  552.         else
  553.             ErrorHandler(XLD_BAD_DIALOG);
  554.  
  555.         FreeMem(lpfpData);
  556.  
  557.         //  set the values
  558.         if (pxValueOut)
  559.         {
  560.             if (CreateGlobalRef(&gxOutRef, &xDialogReturned, SGSMOOTH_OUT_ROW))
  561.             {
  562.                 SetValues(pxValueOut);
  563.             }
  564.         }
  565.  
  566.     }
  567.  
  568.     Excel(xlFree, 0, 1, (LPXLOPER)&xDialogReturned);
  569.  
  570.     return 1;
  571.  
  572. }
  573.  
  574. int FAR PASCAL __export fCalcSpline(void)
  575. {
  576.     int xlRet;
  577.     XLOPER xDialog;
  578.     XLOPER xDialogReturned;
  579.  
  580.     XLOPER xXorig, xCoef, xXcalc, xOut;
  581.     LPXLOPER pxValueOut = NULL;
  582.     LPFP lpfpXorig = NULL;
  583.     LPFP lpfpCoef = NULL;
  584.     LPFP lpfpXcalc = NULL;
  585.  
  586.     if (!GetActiveSheetId())
  587.     {
  588.         // no active sheet; error emit in GetActiveSheet()
  589.         return 0;
  590.     }
  591.  
  592.     // init the dialog xlMulti
  593.     if (InitDialog( (LPXLOPER)&xDialog, &rgDlgCalcSpline[0][0], 
  594.                         rgCalcSplineDlgRows)==NULL)
  595.     {
  596.         return 0;
  597.     }
  598.  
  599.     // get selection in text form for Xorig & Coef
  600.     GetRefTextFromSelection((LPXLOPER)&xXorig, (LPXLOPER)&xCoef, 2);
  601.     GetRefTextFromSelection((LPXLOPER)&xXcalc, (LPXLOPER)&xOut, 6);
  602.     
  603.     // stuff into dialog box
  604.     SetInitialRange((LPXLOPER)&xXorig,  (LPXLOPER)&xDialog, CALCSPLINE_XORIG_ROW);
  605.     SetInitialRange((LPXLOPER)&xCoef, (LPXLOPER)&xDialog, CALCSPLINE_COEF_ROW);
  606.     SetInitialRange((LPXLOPER)&xXcalc, (LPXLOPER)&xDialog, CALCSPLINE_XCALC_ROW);
  607.     SetInitialRange((LPXLOPER)&xOut, (LPXLOPER)&xDialog, CALCSPLINE_OUT_ROW);
  608.  
  609.     // show dialog box
  610.     xlRet =Excel(xlfDialogBox, (LPXLOPER)&xDialogReturned, 1, (LPXLOPER)&xDialog);
  611.  
  612.     // free Excel str & xDialog
  613.     Excel(xlFree,0,1,(LPXLOPER)&xXcalc);
  614.     Excel(xlFree,0,1,(LPXLOPER)&xXorig);
  615.     Excel(xlFree,0,1,(LPXLOPER)&xCoef);
  616.     Excel(xlFree,0,1,(LPXLOPER)&xOut);
  617.     FreeMem((LPVOID)xDialog.val.array.lparray);
  618.     if (xlRet != xlretSuccess || xDialogReturned.xltype != xltypeMulti)
  619.         return 0;
  620.  
  621.     // get Xorig
  622.     if (CreateGlobalRef(&gxInRef, &xDialogReturned, CALCSPLINE_XORIG_ROW))
  623.     {
  624.         Excel(xlCoerce, (LPXLOPER)&xXorig, 1, (LPXLOPER)&gxInRef);
  625.         lpfpXorig = CopyXloperToFp(&xXorig);
  626.         Excel(xlFree, 0, 1, (LPXLOPER)&xXorig);
  627.     }
  628.     if (lpfpXorig == NULL)
  629.         goto abort;
  630.  
  631.     // get Coefs
  632.     if (CreateGlobalRef(&gxInRef, &xDialogReturned, CALCSPLINE_COEF_ROW))
  633.     {
  634.         Excel(xlCoerce, (LPXLOPER)&xCoef, 1, (LPXLOPER)&gxInRef);
  635.         lpfpCoef = CopyXloperToFp(&xCoef);
  636.         Excel(xlFree, 0, 1, (LPXLOPER)&xCoef);
  637.     }
  638.     if (lpfpCoef == NULL)
  639.     {
  640.         FreeMem(lpfpXorig);
  641.         goto abort;
  642.     }
  643.  
  644.     // get Xcalc
  645.     if (CreateGlobalRef(&gxInRef,&xDialogReturned, CALCSPLINE_XCALC_ROW))
  646.     {
  647.         Excel(xlCoerce, (LPXLOPER)&xXcalc, 1, (LPXLOPER)&gxInRef);
  648.         lpfpXcalc = CopyXloperToFp(&xXcalc);
  649.         Excel(xlFree, 0, 1, (LPXLOPER)&xXcalc);
  650.     }
  651.  
  652.     if (lpfpXcalc == NULL)
  653.     {
  654.         FreeMem(lpfpXorig);
  655.         FreeMem(lpfpCoef);
  656.         goto abort;
  657.     }
  658.  
  659.     // call the function
  660.     pxValueOut = CalcSpline(lpfpXorig, lpfpCoef, lpfpXcalc);
  661.     FreeMem(lpfpXorig);
  662.     FreeMem(lpfpCoef);
  663.     FreeMem(lpfpXcalc);
  664.  
  665.     // set the values
  666.     if (pxValueOut)
  667.     {
  668.         if( CreateGlobalRef(&gxOutRef, &xDialogReturned, CALCSPLINE_OUT_ROW))
  669.         {
  670.             SetValues(pxValueOut);
  671.         }
  672.     }
  673. abort:
  674.     Excel(xlFree, 0, 1, (LPXLOPER)&xDialogReturned);
  675.  
  676.     return 1;
  677.  
  678. }
  679.